package com.lineage.server.datatables.sql;

import com.lineage.DatabaseFactoryLogin;
import com.lineage.commons.system.LanSecurityManager;
import com.lineage.config.Config;
import com.lineage.config.ConfigIpCheck;
import com.lineage.server.datatables.lock.IpReading;
import com.lineage.server.datatables.storage.IpStorage;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class IpTable implements IpStorage {
  private static final Log _log = LogFactory.getLog(IpTable.class);
  
  private static IpTable _instance;
  
  private Timestamp _UnbanTime;
  
  public static IpTable get() {
    if (_instance == null)
      _instance = new IpTable(); 
    return _instance;
  }
  
  public Timestamp getUnbanTime() {
    return this._UnbanTime;
  }
  
  public void setUnbanTime(Timestamp time) {
    this._UnbanTime = time;
  }
  
  private void ufwDeny(String key) {
    try {
      if (ConfigIpCheck.UFW) {
        String command = "sudo ufw deny from " + key;
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null;
        while ((line = input.readLine()) != null)
          _log.info("Linux 系统命令执行: 防火墙" + line); 
      } 
    } catch (IOException e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private void ufwDeleteDeny(String key) {
    try {
      String command = "sudo ufw delete deny from " + key;
      Process process = Runtime.getRuntime().exec(command);
      BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
      String line = null;
      while ((line = input.readLine()) != null)
        _log.info("Linux 系统命令执行: 防火墙" + line); 
    } catch (IOException e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactoryLogin.get().getConnection();
      ps = cn.prepareStatement("SELECT * FROM `ban_ip`");
      rs = ps.executeQuery();
      while (rs.next()) {
        String key = rs.getString("ip");
        if (key.lastIndexOf(".") != -1) {
          if (LanSecurityManager.BANIPMAP.containsKey(key))
            continue; 
          LanSecurityManager.BANIPMAP.put(key, Integer.valueOf(100));
          IpReading.get().checktime(key);
          continue;
        } 
        if (LanSecurityManager.BANNAMEMAP.containsKey(key))
          continue; 
        LanSecurityManager.BANNAMEMAP.put(key, Integer.valueOf(100));
        IpReading.get().checktime(key);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    _log.info("载入禁止登入IP资料数量: " + LanSecurityManager.BANIPMAP.size() + "(" + timer.get() + "ms)");
    _log.info("载入禁止登入NAME资料数量: " + LanSecurityManager.BANNAMEMAP.size() + "(" + timer.get() + "ms)");
  }
  
  public void add(String key, String info) {
    boolean isBan = false;
    if (key.lastIndexOf(".") != -1) {
      if (!LanSecurityManager.BANIPMAP.containsKey(key)) {
        LanSecurityManager.BANIPMAP.put(key, Integer.valueOf(100));
        isBan = true;
        if (Config.ISUBUNTU)
          ufwDeny(key); 
      } 
    } else if (!LanSecurityManager.BANNAMEMAP.containsKey(key)) {
      LanSecurityManager.BANNAMEMAP.put(key, Integer.valueOf(100));
      isBan = true;
    } 
    if (check(key))
      isBan = false; 
    if (isBan) {
      Connection con = null;
      PreparedStatement pstm = null;
      try {
        con = DatabaseFactoryLogin.get().getConnection();
        pstm = con
          .prepareStatement("INSERT INTO `ban_ip` SET `ip`=?,`info`=?,`datetime`=SYSDATE(), UnbanTime=?");
        int i = 0;
        pstm.setString(++i, key);
        pstm.setString(++i, info);
        pstm.setTimestamp(++i, getUnbanTime());
        pstm.execute();
      } catch (SQLException e) {
        _log.error(e.getLocalizedMessage(), e);
      } finally {
        SQLUtil.close(pstm);
        SQLUtil.close(con);
      } 
    } 
  }
  
  public void remove(String key) {
    boolean isBan = false;
    if (key.lastIndexOf(".") != -1) {
      if (LanSecurityManager.BANIPMAP.containsKey(key)) {
        LanSecurityManager.BANIPMAP.remove(key);
        isBan = true;
        if (Config.ISUBUNTU) {
          _log.info("******Linux 系统命令执行**************************");
          ufwDeleteDeny(key);
          _log.info("******Linux 系统命令完成**************************");
        } 
      } 
    } else if (LanSecurityManager.BANNAMEMAP.containsKey(key)) {
      LanSecurityManager.BANNAMEMAP.remove(key);
      isBan = true;
    } 
    if (!check(key))
      isBan = false; 
    if (isBan) {
      Connection con = null;
      PreparedStatement pstm = null;
      try {
        con = DatabaseFactoryLogin.get().getConnection();
        pstm = con.prepareStatement("DELETE FROM `ban_ip` WHERE `ip`=?");
        pstm.setString(1, key);
        pstm.execute();
      } catch (SQLException e) {
        _log.error(e.getLocalizedMessage(), e);
      } finally {
        SQLUtil.close(pstm);
        SQLUtil.close(con);
      } 
    } 
  }
  
  private boolean check(String key) {
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactoryLogin.get().getConnection();
      String sqlstr = "SELECT * FROM `ban_ip` WHERE `ip` ='" + key + "'";
      ps = cn.prepareStatement(sqlstr);
      rs = ps.executeQuery();
      if (rs.next())
        return true; 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    return false;
  }
  
  public void checktime(String key) {
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactoryLogin.get().getConnection();
      String sqlstr = "SELECT * FROM `ban_ip` WHERE `ip` ='" + key + "'";
      ps = cn.prepareStatement(sqlstr);
      rs = ps.executeQuery();
      while (rs.next()) {
        Timestamp ts = rs.getTimestamp("UnbanTime");
        if (ts != null && ts.getTime() < System.currentTimeMillis()) {
          IpReading.get().remove(key);
          System.out.println("解除封锁：" + key);
        } 
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
}
